const videoformat = {
    videoFormats: null,
    videoCodecInfos: null,
    audioCodecInfos: null,
    videoCodecs: null,
    audioCodecs: null,
    subtitleCodecs: null,
    init: function () {
        Set.prototype.addAll = function (array) {
            if (array instanceof Array) {
                for (const i in array) {
                    this.add(array[i])
                }
            }
        }
        Map.prototype.putAll = function (map) {
            if (map instanceof Object) {
                for (const key in map) {
                    this.set(key, map[key])
                }
            }
        }
    },
    setDatas: function(videoCodecInfo){
        videoformat.videoFormats = videoCodecInfo.videoFormats
        videoformat.videoCodecInfos = videoCodecInfo.videoCodecInfos
        videoformat.audioCodecInfos = videoCodecInfo.audioCodecInfos

        const codecInfos = videoCodecInfo.codecInfos
        const audioSampleCodecs = codecInfos.audioSampleCodecs
        const audioPCMCodecs = codecInfos.audioPCMCodecs
        const audioADPCMCodecs = codecInfos.audioADPCMCodecs
        videoformat.videoCodecs = codecInfos.videoCodecs
        videoformat.audioCodecs = new Map()
        videoformat.audioCodecs.putAll(audioSampleCodecs)
        videoformat.audioCodecs.putAll(audioPCMCodecs)
        videoformat.audioCodecs.putAll(audioADPCMCodecs)
        videoformat.subtitleCodecs = codecInfos.subtitleCodecs
    },
    getFormats: function (format) {
        const formats = new Set()
        for (const videoFormatName in videoformat.videoFormats) {
            const videoFormat = videoformat.videoFormats[videoFormatName]
            if (format) {
                if (videoFormat.format == format) {
                    formats.add(format)
                }
            } else {
                formats.add(videoFormat.format)
            }
        }
        return formats
    },
    getFormatInfos: function (videoFormatNames, videoCodecName, audioCodecName, subtitleCodec) {
        const videoCodecs = new Set()
        const audioCodecs = new Map()
        const videoFormats = new Set()
        const subtitleCodecs = new Set()
        if (videoFormatNames) {
            videoFormatNames.forEach(function (videoFormatName) {
                videoFormats.add(videoformat.videoFormats[videoFormatName])
            })
        } else {
            videoFormats.addAll(videoformat.videoFormats)
        }
        videoFormats.forEach(function (videoFormat) {
            if (videoCodecName) {
                videoFormat.videoCodecs.forEach(function (videoCodecName2) {
                    if (videoCodecName == videoCodecName2) {
                        videoCodecs.add(videoCodecName)
                    }
                })
            } else {
                videoCodecs.addAll(videoFormat.videoCodecs)
            }
            const audioCodecs2 = videoFormat.audioCodecs
            for (const audioCodecBigName in audioCodecs2) {
                const audioCodecsSmall = audioCodecs2[audioCodecBigName]
                if (audioCodecName) {
                    const audioCodecsSmall2 = new Set()
                    audioCodecsSmall.forEach(function (audioCodecName2) {
                        if (audioCodecName == audioCodecName2) {
                            audioCodecsSmall2.add(audioCodecName)
                        }
                    })
                    audioCodecs.set(audioCodecBigName, audioCodecsSmall2)
                } else {
                    audioCodecs.set(audioCodecBigName, audioCodecsSmall)
                }
            }
            if (subtitleCodec) {
                videoFormat.subtitleCodecs.forEach(function (subtitleCodec2) {
                    if (subtitleCodec2 == subtitleCodec) {
                        subtitleCodecs.add(subtitleCodec)
                    }
                })
            } else {
                subtitleCodecs.addAll(videoFormat.subtitleCodecs)
            }
        })
        return [videoCodecs, audioCodecs, subtitleCodecs]
    },
    getVideoCodecInfos: function (videoCodecNames, pixelFormat, addSdr) {
        const pixelFormats = new Set()
        const addSdrs = new Set()
        const videoCodecs = new Set()
        if (videoCodecNames) {
            videoCodecNames.forEach(function (videoCodecName) {
                const videoCodec = videoformat.videoCodecInfos[videoCodecName]
                if (videoCodec) {
                    videoCodecs.add(videoCodec)
                }
            })
        } else {
            videoCodecs.addAll(videoformat.videoCodecInfos)
        }
        videoCodecs.forEach(function (videoCodec) {
            if (pixelFormat) {
                videoCodec.pixelFormats.forEach(function (pixelFormat2) {
                    if (pixelFormat == pixelFormat2) {
                        pixelFormats.add(pixelFormat)
                    }
                })
            } else {
                pixelFormats.addAll(videoCodec.pixelFormats)
            }
            if (addSdr != null) {
                if (addSdr == videoCodec.addSdr) {
                    addSdrs.add(videoCodec.addSdr)
                }
            } else {
                addSdrs.add(videoCodec.addSdr)
            }
        })
        return [pixelFormats, addSdrs]
    },
    getAudioCodecInfos: function (audioCodecNames, sampleFormat) {
        const sampleFormats = new Set()
        const audioCodecs = new Set()
        if (audioCodecNames) {
            for (const [audioCodecBigName, audioCodecsSmall] of audioCodecNames) {
                audioCodecsSmall.forEach(function (audioCodecName) {
                    const videoCodec = videoformat.audioCodecInfos[audioCodecName]
                    if (videoCodec) {
                        audioCodecs.add(videoCodec)
                    }
                })
            }
        } else {
            audioCodecs.addAll(videoformat.audioCodecInfos)
        }
        audioCodecs.forEach(function (audioCodec) {
            if (sampleFormat) {
                audioCodec.sampleFormats.forEach(function (sampleFormat2) {
                    if (sampleFormat == sampleFormat2) {
                        sampleFormats.add(sampleFormat)
                    }
                })
            } else {
                sampleFormats.addAll(audioCodec.sampleFormats)
            }
        })
        return sampleFormats
    },
    getList: function (format, videoCodecName, pixelFormat, addSdr, subtitleCodec, crf, audioCodecName, sampleFormat) {
        const formats = videoformat.getFormats(format)
        const [videoCodecs, audioCodecs, subtitleCodecs] = videoformat.getFormatInfos(formats, videoCodecName, audioCodecName, subtitleCodec)
        const [pixelFormats, addSdrs] = videoformat.getVideoCodecInfos(videoCodecs, pixelFormat, addSdr)
        const sampleFormats = videoformat.getAudioCodecInfos(audioCodecs, sampleFormat)
        const info = {
            formats: formats,
            videoCodecs: videoCodecs,
            pixelFormats: pixelFormats,
            addSdrs: addSdrs,
            subtitleCodecs: subtitleCodecs,
            audioCodecs: audioCodecs,
            sampleFormats: sampleFormats
        }
        return info
    },
    isEffective: function (formatName, videoCodecName, pixelFormat, addSdr, subtitleCodec, crf, audioCodecName, sampleFormat) {
        let isFormat = false
        let isVideoCodecName = false
        let isPixelFormat = false
        let isAddSdr = false
        let isSubtitleCodec = false
        let isAudioCodecName = false
        let isSampleFormat = false
        let format = videoformat.videoFormats[formatName]
        if (format) {
            isFormat = true
        }
        if (isFormat) {
            format.videoCodecs.forEach(function (videoCodecName2) {
                if (videoCodecName2 == videoCodecName) {
                    isVideoCodecName = true
                    if (isVideoCodecName) {
                        const videoCodec = videoformat.videoCodecInfos[videoCodecName]
                        videoCodec.pixelFormats.forEach(function (pixelFormat2) {
                            if (pixelFormat == pixelFormat2) {
                                isPixelFormat = true
                            }
                        })
                        if (videoCodec.addSdr == addSdr) {
                            isAddSdr = true
                        }
                    }
                }
            })
            format.subtitleCodecs.forEach(function (subtitleCodec2) {
                if (subtitleCodec2 == subtitleCodec) {
                    isSubtitleCodec = true
                }
            })
            const audioCodecs = format.audioCodecs
            for (const audioCodecBigName in audioCodecs) {
                const audioCodecsSmall = audioCodecs[audioCodecBigName]
                audioCodecsSmall.forEach(function (audioCodecName2) {
                    if (audioCodecName2 == audioCodecName) {
                        isAudioCodecName = true
                        if (isAudioCodecName) {
                            const audioCodec = videoformat.audioCodecInfos[audioCodecName2]
                            audioCodec.sampleFormats.forEach(function (sampleFormat2) {
                                if (sampleFormat2 == sampleFormat) {
                                    isSampleFormat = true
                                }
                            })
                        }
                    }
                })
            }
        }
        return isFormat && isVideoCodecName && isPixelFormat && isAddSdr && isSubtitleCodec && isAudioCodecName && isSampleFormat
    },
    parameterTransformation: function (format, videoCodecName, pixelFormat, addSdr, subtitleCodec, crf, audioCodecName, sampleFormat) {
        return [format, videoformat.videoCodecs[videoCodecName], pixelFormat, addSdr, videoformat.subtitleCodecs[subtitleCodec], crf, videoformat.audioCodecs.get(audioCodecName), sampleFormat]
    }
};
module.exports = videoformat;